﻿#include "TextFileReader.h"

#include <QFile>
#include <qmath.h>
#include <QTextStream>
#include <vtkTable.h>
#include <vtkFieldData.h>
#include <vtkStringArray.h>
#include <vtkDoubleArray.h>
#include <vtkVariantArray.h>
#include <vtkAbstractArray.h>
#include <vtkSys/SystemTools.hxx>
#include <vtkDelimitedTextReader.h>

#include "BaseModule/IBaseSignal.h"
#include "CommonFunction.h"
#include "TextArrayMetaHander.h"

namespace
{
    bool contains(const QList<QString>& unitsSet, const QString& target)
    {
        bool contains = false;
        for (const QString& u : unitsSet)
        {
            if (u.compare(target, Qt::CaseInsensitive) == 0)
            {
                contains = true;
                break;
            }
        }
        return contains;
    }

    int getKeyTypeFromUnitString(const QString& unitString)
    {
        QList<QString> frequencyUnits = { "Hz", "KHz", "MHz", "GHz" };
        QList<QString> lengthUnits = { "mm", "cm", "m" };
        QList<QString> angleUnits = { "deg" };
        QList<QString> timeUnits = { "ns", "us", "ms", "s", "min", "h" };

        if (contains(timeUnits, unitString))//时间为1
        {
            return 1;
        }
        if (contains(frequencyUnits, unitString))//频率为2
        {
            return 2;
        }
 
        if (contains(angleUnits, unitString))//角度为3、4
        {
            return 3;
        }
        if (contains(lengthUnits, unitString))//长度为5、6、7
        {
            return 5;
        }
     
        return -2;//-2表示没有单位
    }
}

namespace pst
{
    TextFileReader::TextFileReader(QObject* parent)
        : QObject(parent), m_originalTable(vtkSmartPointer<vtkTable>::New()), m_fileDealType(0), m_fileComponentType(0)
    {
    }

    TextFileReader::~TextFileReader()
    {
    }

    void TextFileReader::SetFileName(const QString& fileName)
    {
        m_fileName = fileName;
    }

    QString TextFileReader::GetFileName()
    {
        return m_fileName;
    }

    void TextFileReader::setFileDealType(int type)
    {
        m_fileDealType = type;
    }

    int TextFileReader::getFileDealType()
    {
        return m_fileDealType;
    }

    void TextFileReader::setFileComponentType(int type)
    {
        m_fileComponentType = type;
    }

    int TextFileReader::getFileComponentType()
    {
        return m_fileComponentType;
    }

    bool TextFileReader::update()
    {
        clearData();
        bool isOk = ReadTxtToVTKTable(m_fileName);
        if (!isOk)
        {
            return false;
        }
        qDebug() << "TextFileReader m_fileName = " << m_fileName;
        qDebug() << "TextFileReader m_flieDealType = " << m_fileDealType;
        qDebug() << "TextFileReader m_fileComponentType = " << m_fileComponentType;

        // 根据文件类型进行处理
        bool isAddOk = addMetaInfomation();

        return isAddOk;
    }

    vtkTable* TextFileReader::getOutputTable()
    {
        return m_originalTable;
    }

    bool TextFileReader::ReadTxtToVTKTable(const QString& filename)
    {
        qDebug() << "ReadTxtToVTKTable =  " << filename;

        QFile file(filename);

        if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        {
            emit IBaseSignalInstance->signal_sendErrorMessageToUI("错误，无法打开文件：" + filename);
            return false;
        }

        QTextStream in(&file);
        in.setCodec("UTF_8");
        QStringList columnNames;

        int lineNumber = 0;
        while (!in.atEnd())
        {
            QString line = in.readLine();
            line.remove('\'');
            line.remove('"'); 

            // Skip the first line (could be a header)
            if (lineNumber == 0)
            {
                m_textHeaderComment = line;
                lineNumber++;
                continue;
            }

            // Remove '#' and leading spaces from the second line
            if (lineNumber == 1)
            {
                m_textHeader = line;
                line.remove(0, line.indexOf(QRegExp("[^#\\s]"))); // Remove leading '#' and spaces
                columnNames = line.split(',', QString::SkipEmptyParts);
                for (const QString& colName : columnNames)
                {
                    auto array = vtkSmartPointer<vtkDoubleArray>::New();
                    array->SetName(colName.toStdString().c_str());
                    m_originalTable->AddColumn(array);
                }
                lineNumber++;
                continue;
            }

            // Read data lines
            QStringList values = line.split(',', QString::SkipEmptyParts);

            if (values.size() != columnNames.size())
            {
                emit IBaseSignalInstance->signal_sendErrorMessageToUI("错误，格式错误，行号：" + QString::number(lineNumber));

                return false;
            }

            vtkNew<vtkVariantArray> rowData;
            for (vtkIdType col = 0; col < values.size(); col++)
            {
                auto value = values.at(col).toDouble();
                rowData->InsertNextValue(value);
            }
            m_originalTable->InsertNextRow(rowData);
            lineNumber++;
        }

        vtkNew<vtkStringArray> annotations;
        annotations->SetName("HeadComment");
        annotations->SetNumberOfValues(1);
        annotations->SetValue(0, m_textHeaderComment.toStdString().c_str());
        m_originalTable->GetFieldData()->AddArray(annotations);

        vtkNew<vtkStringArray> headerText;
        headerText->SetName("Header");
        headerText->SetNumberOfValues(1);
        headerText->SetValue(0, m_textHeader.toStdString().c_str());
        m_originalTable->GetFieldData()->AddArray(headerText);

        file.close();
        return true;
    }

    bool TextFileReader::parseTitleName(vtkTable* inputTable,
        QVector<QString>& eachColNameOfKey, QVector<QString>& eachColUnitOfKey,
        QVector<QString>& eachColNameOfValue, QVector<QString>& eachColUnitOfValue)
    {
        if (inputTable == nullptr)
        {
            m_errorMessage = "inputTable is null!";
            return false;
        }

        for (int i = 0; i < inputTable->GetNumberOfColumns(); ++i)
        {
            QString arrayName = QString(inputTable->GetColumn(i)->GetName()).trimmed();
            QStringList splitList = arrayName.split("||", QString::SkipEmptyParts);
            if (splitList.size() != 3)
            {
                qDebug() << " Warning! File format illegal : " << m_fileName;
                m_errorMessage = "File format illegal!";
                return false;
            }

            // 判断是key还是value
            QString type = splitList[2].trimmed();
            if (type.toUpper() == "KEY")
            {
                eachColNameOfKey.append(splitList[0].trimmed());
                eachColUnitOfKey.append(splitList[1].trimmed());
            }
            else if (type.toUpper() == "VALUE")
            {
                eachColNameOfValue.append(splitList[0]);
                eachColUnitOfValue.append(splitList[1]);
            }
            else
            {
                qDebug() << " Warning! File format illegal, type is " << type << " in " << m_fileName;
                m_errorMessage = "File format illegal, type is " + type;
                return false;
            }
        }

        return true;
    }

    bool TextFileReader::addMetaInfomation()
    {
        QVector<QString> eachColNameOfKey;
        QVector<QString> eachColUnitOfKey;
        QVector<QString> eachColNameOfValue;
        QVector<QString> eachColUnitOfValue;
        if (!parseTitleName(m_originalTable, eachColNameOfKey, eachColUnitOfKey,
            eachColNameOfValue, eachColUnitOfValue))
        {
            return false;
        }

        // 先添加key列
        for (int i = 0; i < eachColNameOfKey.size(); i++)
        {
            auto keyArray = m_originalTable->GetColumn(i);
            auto name = eachColUnitOfKey[i];
            int keyType = getKeyTypeFromUnitString(name);

            QFileInfo fileInfo(m_fileName);
            TextArrayMetaStruct metaStruct(m_fileName, fileInfo.fileName(), keyType, 4, eachColNameOfKey[i],
                -1, -1, -1, -1, i, eachColUnitOfKey[i], 0);
            TextArrayMetaHander::setArrayMeta(keyArray, metaStruct);
        }

        // 处理value列
        if (m_fileDealType == 7) // 增益文件处理
        {
            if (m_fileComponentType == 0)
            {
                for (int i = 0; i < eachColNameOfValue.size(); ++i)
                {
                    auto _scalarArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i));
                    auto scalarName = eachColNameOfValue[i];
                    QFileInfo fileInfo(m_fileName);

                    TextArrayMetaStruct metaStructReal(m_fileName, fileInfo.fileName(), 7, 4, scalarName,
                        -1, -1, -1, -1, eachColNameOfKey.size() + i, eachColUnitOfValue[i], 1);
                    TextArrayMetaHander::setArrayMeta(_scalarArray, metaStructReal);
                }
            }
            else if (eachColNameOfValue.size() % 2 != 1)
            {
                qDebug() << "File format illegal! Value array must be odd!";
                return false;
            }
            else if (m_fileComponentType == 1) // 实部虚部模式
            {
                for (int i = 0; i < eachColNameOfValue.size() - 1; i += 2) // 去除最后一个增益列
                {
                    auto realArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i));
                    auto imgArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i + 1));

                    auto realName = eachColNameOfValue[i];
                    auto imgName = eachColNameOfValue[i + 1];

                    QString commonName1;
                    QString commonName2;
                    bool isSuc1 = CommonFunction::extractContentBetweenParentheses(realName, commonName1);
                    bool isSuc2 = CommonFunction::extractContentBetweenParentheses(imgName, commonName2);

                    if (!isSuc1 || !isSuc2 || (commonName1 != commonName2))
                    {
                        qDebug() << "Error! Col name not illegal.";
                        return false;
                    }

                    int realArrayIndex = eachColNameOfKey.size() + i;
                    int imgArrayIndex = eachColNameOfKey.size() + i + 1;

                    QFileInfo fileInfo(m_fileName);
                    TextArrayMetaStruct metaStructReal(m_fileName, fileInfo.fileName(), 1, 0, commonName1,
                        realArrayIndex, imgArrayIndex, -1, -1, -1, eachColUnitOfValue[i], 1);
                    TextArrayMetaStruct metaStructImg(m_fileName, fileInfo.fileName(), 1, 1, commonName1,
                        realArrayIndex, imgArrayIndex, -1, -1, -1, eachColUnitOfValue[i + 1], 1);

                    TextArrayMetaHander::setArrayMeta(realArray, metaStructReal);
                    TextArrayMetaHander::setArrayMeta(imgArray, metaStructImg);
                }

                auto _gainArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + eachColNameOfValue.size() - 1));

                QFileInfo fileInfo(m_fileName);
                TextArrayMetaStruct metaStructGain(m_fileName, fileInfo.fileName(), 7, 4, eachColNameOfValue.last(),
                    -1, -1, -1, -1, m_originalTable->GetNumberOfColumns() - 1, eachColUnitOfValue.last(), 1);
                TextArrayMetaHander::setArrayMeta(_gainArray, metaStructGain);
            }
            else if (m_fileComponentType == 2) // 幅度相位模式
            {
                for (int i = 0; i < eachColNameOfValue.size() - 1; i += 2)
                {
                    auto magArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i));
                    auto phaseArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i + 1));

                    auto magName = eachColNameOfValue[i];
                    auto phaseName = eachColNameOfValue[i + 1];

                    QString commonName1;
                    QString commonName2;
                    bool isSuc1 = CommonFunction::extractContentBetweenParentheses(magName, commonName1);
                    bool isSuc2 = CommonFunction::extractContentBetweenParentheses(phaseName, commonName2);
                    if (!isSuc1 || !isSuc2 || (commonName1 != commonName2))
                    {
                        qDebug() << "Error! Col name not illegal.";
                        return false;
                    }

                    int magArrayIndex = eachColNameOfKey.size() + i;
                    int phaseArrayIndex = eachColNameOfKey.size() + i + 1;

                    QFileInfo fileInfo(m_fileName);
                    TextArrayMetaStruct metaStructMag(m_fileName, fileInfo.fileName(), 1, 2, commonName1,
                        -1, -1, magArrayIndex, phaseArrayIndex, -1, eachColUnitOfValue[i], 1);
                    TextArrayMetaStruct metaStructPhase(m_fileName, fileInfo.fileName(), 1, 3, commonName1,
                        -1, -1, magArrayIndex, phaseArrayIndex, -1, eachColUnitOfValue[i + 1], 1);

                    TextArrayMetaHander::setArrayMeta(magArray, metaStructMag);
                    TextArrayMetaHander::setArrayMeta(phaseArray, metaStructPhase);
                }

                auto _gainArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + eachColNameOfValue.size() - 1));

                QFileInfo fileInfo(m_fileName);
                TextArrayMetaStruct metaStructGain(m_fileName, fileInfo.fileName(), 7, 4, eachColNameOfValue.last(),
                    -1, -1, -1, -1, m_originalTable->GetNumberOfColumns() - 1, eachColUnitOfValue.last(), 1);
                TextArrayMetaHander::setArrayMeta(_gainArray, metaStructGain);
            }
        }
        else
        {
            int resultParaType = 0;
            switch (m_fileDealType)
            {
            case 0:
            case 1:
            case 2:
                resultParaType = 0;
                break;
            default:
                resultParaType = m_fileDealType;
                break;
            }
            if (m_fileComponentType == 0)
            {
                for (int i = 0; i < eachColNameOfValue.size(); ++i)
                {
                    auto _scalarArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i));
                    auto scalarName = eachColNameOfValue[i];
                    QFileInfo fileInfo(m_fileName);

                    TextArrayMetaStruct metaStructReal(m_fileName, fileInfo.fileName(), resultParaType, 4, scalarName,
                        -1, -1, -1, -1, eachColNameOfKey.size() + i, eachColUnitOfValue[i], 1);
                    TextArrayMetaHander::setArrayMeta(_scalarArray, metaStructReal);
                }
            }
            else if (eachColNameOfValue.size() % 2 != 0)
            {
                qDebug() << "File format illegal! Value array must be even!";
                return false;
            }
            else if (m_fileComponentType == 1) // 实部虚部模式
            {
                for (int i = 0; i < eachColNameOfValue.size(); i += 2)
                {
                    auto realArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i));
                    auto imgArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i + 1));

                    auto realName = eachColNameOfValue[i];
                    auto imgName = eachColNameOfValue[i + 1];

                    QString commonName1;
                    QString commonName2;
                    bool isSuc1 = CommonFunction::extractContentBetweenParentheses(realName, commonName1);
                    bool isSuc2 = CommonFunction::extractContentBetweenParentheses(imgName, commonName2);
                    if (!isSuc1 || !isSuc2 || (commonName1 != commonName2))
                    {
                        qDebug() << "Error! Col name not illegal.";
                        return false;
                    }

                    int realArrayIndex = eachColNameOfKey.size() + i;
                    int imgArrayIndex = eachColNameOfKey.size() + i + 1;

                    QFileInfo fileInfo(m_fileName);
                    TextArrayMetaStruct metaStructReal(m_fileName, fileInfo.fileName(), resultParaType, 0, commonName1,
                        realArrayIndex, imgArrayIndex, -1, -1, -1, eachColUnitOfValue[i], 1);
                    TextArrayMetaStruct metaStructImg(m_fileName, fileInfo.fileName(), resultParaType, 1, commonName1,
                        realArrayIndex, imgArrayIndex, -1, -1, -1, eachColUnitOfValue[i + 1], 1);

                    TextArrayMetaHander::setArrayMeta(realArray, metaStructReal);
                    TextArrayMetaHander::setArrayMeta(imgArray, metaStructImg);
                }
            }
            else if (m_fileComponentType == 2) // 幅度相位模式
            {
                for (int i = 0; i < eachColNameOfValue.size(); i += 2)
                {
                    auto magArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i));
                    auto phaseArray = vtkDoubleArray::SafeDownCast(m_originalTable->GetColumn(eachColNameOfKey.size() + i + 1));

                    auto rName = eachColNameOfValue[i];
                    auto thetaName = eachColNameOfValue[i + 1];

                    QString commonName1;
                    QString commonName2;
                    bool isSuc1 = CommonFunction::extractContentBetweenParentheses(rName, commonName1);
                    bool isSuc2 = CommonFunction::extractContentBetweenParentheses(thetaName, commonName2);
                    if (!isSuc1 || !isSuc2 || (commonName1 != commonName2))
                    {
                        qDebug() << "Error! Col name not illegal.";
                        return false;
                    }

                    int magArrayIndex = eachColNameOfKey.size() + i;
                    int phaseArrayIndex = eachColNameOfKey.size() + i + 1;

                    QFileInfo fileInfo(m_fileName);
                    TextArrayMetaStruct metaStructMag(m_fileName, fileInfo.fileName(), resultParaType, 2, commonName1,
                        -1, -1, magArrayIndex, phaseArrayIndex, -1, eachColUnitOfValue[i], 1);
                    TextArrayMetaStruct metaStructPhase(m_fileName, fileInfo.fileName(), resultParaType, 3, commonName1,
                        -1, -1, magArrayIndex, phaseArrayIndex, -1, eachColUnitOfValue[i + 1], 1);

                    TextArrayMetaHander::setArrayMeta(magArray, metaStructMag);
                    TextArrayMetaHander::setArrayMeta(phaseArray, metaStructPhase);
                }
            }
        }

        return true;
    }

    void TextFileReader::clearData()
    {
        // m_eachColNameOfKey.clear();
        // m_eachColUnitOfKey.clear();
        // m_eachColDataOfKey.clear();
        // m_eachColNameOfValue.clear();
        // m_eachColUnitOfValue.clear();
        // m_eachColDataOfValue.clear();
    }

    // TextArrayMetaStruct TextFileReader::addArrayMetaStruct(const QString& filePath,
    //     int resultParaType, int resultDataType, const QString& dataGroupNam,
    //     int relatedScalarIndex, int relatedRealPartIndex, int relatedImagPartIndex,
    //     int relatedMagPartIndex, int relatedPhasePartIndex, const QString& unit, int keyValueType)
    //{
    //     TextArrayMetaStruct metaStruct;

    //    //添加meta信息
    //    QFileInfo fileInfo(filePath);
    //    metaStruct.filePath = filePath;
    //    metaStruct.fileName = fileInfo.fileName();
    //    metaStruct.resultParaType = resultParaType;
    //    metaStruct.resultDataType = resultDataType;
    //    metaStruct.dataGroupName = dataGroupNam;
    //    metaStruct.relatedScalarIndex = relatedScalarIndex;
    //    metaStruct.relatedRealPartIndex = relatedRealPartIndex;
    //    metaStruct.relatedImagPartIndex = relatedImagPartIndex;
    //    metaStruct.relatedMagPartIndex = relatedMagPartIndex;
    //    metaStruct.relatedPhasePartIndex = relatedPhasePartIndex;
    //    metaStruct.unit = unit;
    //    metaStruct.keyValueType = keyValueType;

    //    return metaStruct;
    //}
} // namespace pst
